package com.btb.adapter.service;

import static java.util.stream.Collectors.joining;

import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.web3j.abi.EventEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Event;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.core.methods.response.EthBlockNumber;
import org.web3j.protocol.core.methods.response.EthLog;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;

import com.btb.adapter.model.MonitorTransferRequest;

/**
 */
@Service
public class EventService {
	private static final Logger LOG = LoggerFactory.getLogger(EventService.class);
	private ThreadLocal<Set<BigInteger>> blockNumberSet = ThreadLocal.withInitial(HashSet::new);

	@Autowired
	private Web3j web3j;

	public String getClientVersion() {
		try {
			Web3ClientVersion web3ClientVersion = web3j.web3ClientVersion().send();
			return web3ClientVersion.getWeb3ClientVersion();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "";
	}

	/**
	 * 区块数量
	 */
	public BigInteger getBlockNumber() {
		EthBlockNumber send;
		try {
			send = web3j.ethBlockNumber().send();
			return send.getBlockNumber();
		} catch (IOException e) {
			LOG.warn("请求区块链信息异常 >> 区块数量,{}", e);
		}
		return null;
	}

	/**
	 * 监听合约
	 */
	public void contractFilter(MonitorTransferRequest monitorTransferRequest) {
		Event event = new Event("Transfer", Arrays.asList(new TypeReference<Address>() {
		}, new TypeReference<Address>() {
		}, new TypeReference<Uint256>() {
		}));
		EthFilter filter = new EthFilter(
				DefaultBlockParameter.valueOf(new BigInteger(monitorTransferRequest.getFirstBlock())),
				DefaultBlockParameter.valueOf(new BigInteger(monitorTransferRequest.getLastBlock())),
				monitorTransferRequest.getContractAddress());
		Event change = new Event("Change", Arrays.asList(new TypeReference<Address>() {
		}, new TypeReference<Address>() {
		}, new TypeReference<Uint256>() {
		}));
		filter.addSingleTopic(EventEncoder.encode(event));
		filter.addSingleTopic(EventEncoder.encode(change));
		// 监听并处理
		contractExtract(filter);
	}

	public void contractExtract(EthFilter filter) {
		try {
			EthLog logs = web3j.ethGetLogs(filter).send();
			logs.getLogs().forEach(r -> {
				Log log = (Log) r;
				BigInteger blockNumber = log.getBlockNumber();
				List<String> topics = log.getTopics();
				String data = log.getData();
				System.out.println("blockNumber:" + blockNumber + " topics:" + topics.stream().collect(joining(","))
						+ " data: " + data);
			});
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}